﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
using System.Web.ClientServices;
using System.Windows.Forms;
using DevExpress.XtraBars;
using DevExpress.XtraEditors;
using DevExpress.XtraEditors.Controls;
using DevExpress.XtraEditors.Repository;
using DevExpress.XtraGrid;
using DevExpress.XtraGrid.Menu;
using DevExpress.XtraGrid.Views.Grid;
using RedRiver.Framework.XtraCommon.Properties;
using RedRiver.Framework.XtraCommon.Reports;
using RedRiver.Framework.XtraCommon.Templates;
using RedRiver.Framework.XtraCommon.UserAuthentication;

namespace RedRiver.Framework.XtraCommon.XtraControls{
    /// <summary>
    /// 工具栏命令适配器
    /// </summary>
    public static class CommandBarItemAdapter{
        public static void AddCommand(this BarLinksHolder bar, params ICommand[] commands){
            foreach (ICommand command in commands){
                var buttonItem = new BarButtonItem(bar.Manager, command.Caption){
                                                                                    Caption = command.Caption,
                                                                                    Name = command.Name,
                                                                                    Description = command.Description,
                                                                                    Tag = command
                                                                                };
                if (command is IBarItemCommand){
                    buttonItem.Glyph = ((IBarItemCommand) command).Glyph;
                    buttonItem.PaintStyle = ((IBarItemCommand) command).PaintStyle;
                }
                buttonItem.ItemClick += ButtonItemItemClick;
                bar.ItemLinks.Add(buttonItem);
            }
        }

        private static void ButtonItemItemClick(object sender, ItemClickEventArgs e){
            var barManager = (BarManager) sender;
            object context = null;
            if (e.Item.Tag is ICommand){
                if (barManager.Form != null){
                    var form = barManager.Form;
                    if (form is IReport){
                        context = ((IReportable) form).GetContext();
                    } else if (form is DataViewForm){
                        context = ((DataViewForm) form).DefaultBindingSource;
                    }
                    ((ICommand) e.Item.Tag).Execute(context, form);
                } else{
                    ((ICommand) e.Item.Tag).Execute();
                }
            }
        }
    }



    public interface ICommand
    {/// <summary>
        /// 当命令被执行后引发该事件
        /// </summary>
        //event EventHandler CommandExecuted;
        /// <summary>
        /// 命令ID
        /// </summary>
        string CommandId { get; }

        /// <summary>
        /// 命令名称(显示名称)
        /// </summary>
        string Name { get; }

        /// <summary>
        /// 命令描述
        /// </summary>
        string Description { get; }

        /// <summary>
        /// 命令标题
        /// </summary>
        string Caption { get; }

        /// <summary>
        /// 执行命令
        /// </summary>
        void Execute();

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandContext">命令上下文</param>
        void Execute(object commandContext);

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandContext">命令上下文</param>
        /// <param name="viewSite">执行界面位置</param>
        void Execute(object commandContext, Control viewSite);
    }

    /// <summary>
    /// 工具栏项目命令接口
    /// </summary>
    public interface IBarItemCommand{
        /// <summary>
        /// 工具栏图标
        /// </summary>
        Image Glyph{
            get;
        }

        BarItemPaintStyle PaintStyle{
            get;
        }
    }

    /// <summary>
    /// 抽象的工具栏命令
    /// </summary>
    public abstract class AbstractBarItemCommand : ICommand, IBarItemCommand{
        #region Implementation of ICommand

        /// <summary>
        /// Gets or sets the object that contains data about the control.
        /// An System.Object that contains data about the control. The default is null.
        /// </summary>
        public object Tag{
            get;
            set;
        }

        /// <summary>
        /// 当命令被执行后引发该事件
        /// </summary>
        //event EventHandler CommandExecuted;
        /// <summary>
        /// 命令ID
        /// </summary>
        public string CommandId{
            get { return GetType().FullName; }
        }

        /// <summary>
        /// 命令名称(显示名称)
        /// </summary>
        public virtual string Name{
            get { return Caption; }
        }

        /// <summary>
        /// 命令描述
        /// </summary>
        public abstract string Description{
            get;
        }

        /// <summary>
        /// 命令标题
        /// </summary>
        public abstract string Caption{
            get;
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        public virtual void Execute(){
            throw new NotImplementedException("没有实现 Execute() 方法.");
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandContext">命令上下文</param>
        public virtual void Execute(object commandContext){
            throw new NotImplementedException("没有实现 Execute(object commandContext) 方法.");
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandContext">命令上下文</param>
        /// <param name="viewSite">执行界面位置</param>
        public abstract void Execute(object commandContext, Control viewSite);

        #endregion

        #region Implementation of IBarItemCommand

        /// <summary>
        /// 工具栏图标
        /// </summary>
        public virtual Image Glyph{
            get { return Resources.Action_SimpleAction; }
        }

        public virtual BarItemPaintStyle PaintStyle{
            get { return BarItemPaintStyle.CaptionGlyph; }
        }

        #endregion
    }

    /// <summary>
    /// 通用类型的命令
    /// </summary>
    public class CommonActionCommand : AbstractBarItemCommand{
        private readonly string _caption;
        private readonly string _description;
        private readonly Image _glyph;
        private readonly EventHandler _handler;

        /// <summary>
        /// 通用类型的命令 构造方法
        /// </summary>
        /// <param name="caption">标题</param>
        /// <param name="description">描述</param>
        /// <param name="handler">执行句柄</param>
        public CommonActionCommand(string caption, string description, EventHandler handler){
            _caption = caption;
            _description = description;
            _handler = handler;
        }

        /// <summary>
        /// 通用类型的命令 构造方法
        /// </summary>
        /// <param name="caption">标题</param>
        /// <param name="description">描述</param>
        /// <param name="glyph">图标</param>
        /// <param name="handler">执行句柄</param>
        public CommonActionCommand(string caption, string description, Image glyph, EventHandler handler){
            _caption = caption;
            _description = description;
            _handler = handler;
            _glyph = glyph;
        }

        #region Overrides of AbstractBarItemCommand

        /// <summary>
        /// 命令描述
        /// </summary>
        public override string Description{
            get { return _description; }
        }

        /// <summary>
        /// 工具栏图标
        /// </summary>
        public override Image Glyph{
            get{
                if (_glyph != null){
                    return _glyph;
                }
                return base.Glyph;
            }
        }

        /// <summary>
        /// 命令标题
        /// </summary>
        public override string Caption{
            get { return _caption; }
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandContext"></param>
        public override void Execute(object commandContext){
            OnAction(EventArgs.Empty);
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandContext">命令上下文</param>
        /// <param name="viewSite">执行界面位置</param>
        public override void Execute(object commandContext, Control viewSite){
            OnAction(EventArgs.Empty);
        }

        /// <summary>
        /// 响应 命令执行事件
        /// </summary>
        /// <param name="e"></param>
        private void OnAction(EventArgs e){
            if (_handler != null){
                _handler(this, e);
            }
        }

        #endregion
    }

    /// <summary>
    /// 超级链接编辑器 打开链接命令
    /// </summary>
    public class HyperLinkActionCommandBase : AbstractBarItemCommand{
        private readonly HyperLinkEdit _hyperLinkEdit;
        private Form _ownerForm;

        #region Overrides of AbstractBarItemCommand

        public HyperLinkActionCommandBase(HyperLinkEdit edit){
            _hyperLinkEdit = edit;
            edit.OpenLink += HyperLinkEditOpenLink;
            _ownerForm = edit.FindForm();
        }

        public HyperLinkActionCommandBase(RepositoryItemHyperLinkEdit edit){
            edit.OpenLink += HyperLinkEditOpenLink;
        }

        protected HyperLinkActionCommandBase(){}

        protected Form OwnerForm{
            get { return _ownerForm; }
        }

        /// <summary>
        /// 命令描述
        /// </summary>
        public override string Description{
            get { return "打开链接"; }
        }

        /// <summary>
        /// 命令标题
        /// </summary>
        public override string Caption{
            get { return "导航链接"; }
        }

        public override Image Glyph{
            get { return Resources.Action_LinkUnlink_Link; }
        }

        protected ButtonEdit HyperLinkEdit{
            get { return _hyperLinkEdit; }
        }

        /// <summary>
        /// 附加 HyperLink 控件 响应 OpenLink 事件
        /// </summary>
        /// <param name="edit"></param>
        public void AttachHyperLink(HyperLinkEdit edit){
            edit.OpenLink += HyperLinkEditOpenLink;
        }

        /// <summary>
        /// 附加 RepositoryItemHyperLinkEdit 控件 响应 OpenLink 事件
        /// </summary>
        /// <param name="edit"></param>
        public void AttachHyperLink(RepositoryItemHyperLinkEdit edit){
            edit.OpenLink += HyperLinkEditOpenLink;
        }

        /// <summary>
        /// 手动打开链接
        /// </summary>
        /// <param name="ownerForm"></param>
        /// <param name="editValue"></param>
        public void OpenLink(Form ownerForm, object editValue){
            if ((ownerForm == null) ||
                (editValue == null)){
                return;
            }
            _ownerForm = ownerForm;
            var e = new OpenLinkEventArgs(editValue);
            if (ownerForm.InvokeRequired){
                ownerForm.Invoke(new Action<OpenLinkEventArgs>(OnOpenLink), e);
            } else{
                OnOpenLink(e);
            }
        }

        protected void HyperLinkEditOpenLink(object sender, OpenLinkEventArgs e){
            if ((sender != null) &&
                (sender is Control)){
                var senderControl = (Control) sender;
                if (e.EditValue == null){
                    return;
                }
                _ownerForm = senderControl.FindForm();
                if (senderControl.InvokeRequired){
                    senderControl.Invoke(new Action<OpenLinkEventArgs>(OnOpenLink), e);
                } else{
                    OnOpenLink(e);
                }
            }
        }

        protected virtual void OnOpenLink(OpenLinkEventArgs e){}

        public override void Execute(){
            HyperLinkEditOpenLink(HyperLinkEdit, new OpenLinkEventArgs(_hyperLinkEdit.EditValue));
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandContext">命令上下文</param>
        /// <param name="viewSite">执行界面位置</param>
        public override void Execute(object commandContext, Control viewSite){
            Execute();
        }

        #endregion
    }

    /// <summary>
    /// 打开窗口命令
    /// </summary>
    public class HyperLinkOpenFormCommand : HyperLinkActionCommandBase{
        private readonly EventHandler<OpenLinkEventArgs> _formOpeningHandler;
        private readonly Type _formType;

        public HyperLinkOpenFormCommand(Type formType){
            if (!formType.IsSubclassOf(typeof (Form))){
                throw new ArgumentException(@"formType 参数必须是一个Form类型的子类", "formType");
            }
            _formType = formType;
        }

        public HyperLinkOpenFormCommand(Type formType, EventHandler<OpenLinkEventArgs> formOpeningHandler)
            : this(formType){
            _formOpeningHandler = formOpeningHandler;
        }

        public HyperLinkOpenFormCommand(HyperLinkEdit edit, Type formType) : base(edit){
            if (!formType.IsSubclassOf(typeof (Form))){
                throw new ArgumentException(@"formType 参数必须是一个Form类型的子类", "formType");
            }
            _formType = formType;
        }

        public HyperLinkOpenFormCommand(HyperLinkEdit edit, Type formType,
                                        EventHandler<OpenLinkEventArgs> formOpeningHandler) : this(edit, formType){
            _formOpeningHandler = formOpeningHandler;
        }

        public HyperLinkOpenFormCommand(RepositoryItemHyperLinkEdit edit, Type formType) : base(edit){
            if (!formType.IsSubclassOf(typeof (Form))){
                throw new ArgumentException(@"formType 参数必须是一个Form类型的子类", "formType");
            }
            _formType = formType;
        }

        public HyperLinkOpenFormCommand(RepositoryItemHyperLinkEdit edit, Type formType,
                                        EventHandler<OpenLinkEventArgs> formOpeningHandler) : this(edit, formType){
            _formOpeningHandler = formOpeningHandler;
        }

        protected override void OnOpenLink(OpenLinkEventArgs e){
            if (e.EditValue == null){
                return;
            }
            Form form = GetForm();
            if (form == null){
                return;
            }
            OnFormOpening(form, e);
            form.Show();
            form.Activate();
        }

        protected virtual void OnFormOpening(Form targetForm, OpenLinkEventArgs e){
            if (_formOpeningHandler != null){
                _formOpeningHandler(targetForm, e);
            }
        }

        /*private static void InvokeMethod(Form form, string methodName){
            if (!string.IsNullOrEmpty(methodName)){
                MethodInfo methodInfo = form.GetType().GetMethod(methodName, new Type[0]);
                if (methodInfo != null){
                    methodInfo.Invoke(form, new object[0]);
                }
            }
        }*/

        /// <summary>
        /// 根据窗体类型获取窗体实例
        /// </summary>
        /// <returns></returns>
        protected Form GetForm(){
            if (_formType != null){
                Form parentForm = OwnerForm.FindForm();
                if (parentForm == null){
                    parentForm = OwnerForm;
                }
                return GetFormCore(parentForm, _formType);
            }
            return null;
        }

        private static Form GetFormCore(Form ownerForm, Type formType){
            try{
                if (ownerForm.IsMdiChild){
                    foreach (Form item in ownerForm.MdiParent.MdiChildren){
                        if (item.GetType().Equals(formType)){
                            return item;
                        }
                    }
                }
            } catch (Exception ex){
                Trace.WriteLine(ex);
            }
            var form = (Form) Activator.CreateInstance(formType);
            if (ownerForm.IsMdiChild){
                form.MdiParent = ownerForm.MdiParent;
            }
            form.WindowState = FormWindowState.Maximized;
            return form;
        }
    }

    /// <summary>
    /// 超级链接编辑器 打开链接命令,打开URL页面
    /// </summary>
    public class HyperLinkOpenURLCommand : HyperLinkActionCommandBase{
        public const string BaseURLMask = "{BaseUrl}";
        public const string EditValueMask = "{EditValue}";
        private readonly string[] _args;

        public HyperLinkOpenURLCommand(string linkFormula, params string[] args){
            LinkFormula = linkFormula;
            _args = args;
            LinkFormula = linkFormula;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="edit"></param>
        /// <param name="linkFormula">链接格式字符串,
        /// {BaseUrl} 替换 <see cref="UserContext.BaseInfo.BaseUrl"/>
        /// {EditValue} 替换 <see cref="HyperLinkEdit.EditValue"/>
        /// </param>
        /// <param name="args"></param>
        public HyperLinkOpenURLCommand(HyperLinkEdit edit, string linkFormula, params string[] args) : base(edit){
            LinkFormula = linkFormula;
            _args = args;
            LinkFormula = linkFormula;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="edit"></param>
        /// <param name="linkFormula">链接格式字符串,
        /// {BaseUrl} 替换 <see cref="UserContext.BaseInfo.BaseUrl"/>
        /// {EditValue} 替换 <see cref="HyperLinkEdit.EditValue"/>
        /// </param>
        /// <param name="args"></param>
        public HyperLinkOpenURLCommand(RepositoryItemHyperLinkEdit edit, string linkFormula, params string[] args)
            : base(edit){
            LinkFormula = linkFormula;
            _args = args;
            LinkFormula = linkFormula;
        }

        [DefaultValue(EditValueMask)]
        public string LinkFormula{
            get;
            set;
        }

        protected override void OnOpenLink(OpenLinkEventArgs e){
            RevalidateUser();
            GetWebForm(OwnerForm, GetLinkUrl(e.EditValue)).Show();
        }

        private static Form GetWebForm(Form ownerForm, string url){
            string fullUrl = url;
            try{
                if (ownerForm.IsMdiChild){
                    foreach (Form item in ownerForm.MdiParent.MdiChildren){
                        if (item is WebPageForm){
                            var page = (WebPageForm) item;
                            if (page.Uri != null){
                                if (page.Url.Equals(fullUrl)){
                                    item.Activate();
                                    return item;
                                }
                            }
                        }
                    }
                }
            } catch (Exception ex){
                Trace.WriteLine(ex);
            }
            var form = new WebPageForm();
            if (ownerForm.IsMdiChild){
                form.MdiParent = ownerForm.MdiParent;
            }
            form.WindowState = FormWindowState.Maximized;
            form.Url = url;
            return form;
        }

        private static void RevalidateUser(){
            if (Thread.CurrentPrincipal.Identity is ClientFormsIdentity){
                try{
                    ((ClientFormsIdentity) Thread.CurrentPrincipal.Identity).RevalidateUser();
                } catch (Exception ex){
                    Trace.WriteLine(ex);
                }
            }
        }

        /// <summary>
        /// 获取链接路径
        /// </summary>
        /// <param name="editValue"></param>
        /// <returns></returns>
        protected virtual string GetLinkUrl(object editValue){
            string link = LinkFormula.Replace(BaseURLMask, UserContext.GlobalConst.BaseUrl);
            link = link.Replace(EditValueMask, editValue.ToString());
            link = string.Format(link, _args);
            return link;
        }
    }

    public class ExcuteActionCommand : AbstractBarItemCommand{
        private readonly Action _action;
        private readonly string _caption;

        #region Overrides of AbstractBarItemCommand

        public ExcuteActionCommand(string caption, Action action){
            _caption = caption;
            _action = action;
        }

        /// <summary>
        /// 命令描述
        /// </summary>
        public override string Description{
            get { return "执行 " + Caption; }
        }

        /// <summary>
        /// 命令标题
        /// </summary>
        public override string Caption{
            get { return _caption; }
        }

        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="commandContext">命令上下文</param>
        /// <param name="viewSite">执行界面位置</param>
        public override void Execute(object commandContext, Control viewSite){
            if (viewSite.InvokeRequired){
                viewSite.Invoke(_action);
            } else{
                _action.Invoke();
            }
        }

        #endregion
    }


    /// <summary>
    /// GridView 菜单命令
    /// </summary>
    public class GridViewMenuCommand : CommonActionCommand{
        #region 静态方法

        private static readonly Dictionary<GridView, List<GridViewMenuCommand>> GridViewMenuCommandMap =
            new Dictionary<GridView, List<GridViewMenuCommand>>();

        public static void AddCommand(GridControl gridControl, params GridViewMenuCommand[] commands){
            if ((commands == null) || (commands.Length == 0)){
                return;
            }
            foreach (object view in gridControl.Views){
                if (view is GridView){
                    AddCommand((GridView) view, commands);
                }
            }
        }

        public static void AddCommand(GridView gridView, params GridViewMenuCommand[] commands){
            if ((commands == null) || (commands.Length == 0)){
                return;
            }
            if (!GridViewMenuCommandMap.ContainsKey(gridView)){
                GridViewMenuCommandMap.Add(gridView, new List<GridViewMenuCommand>());
            }
            GridViewMenuCommandMap[gridView].AddRange(commands);

            gridView.PopupMenuShowing += GridViewShowGridMenu;
            gridView.Disposed += GridViewDisposed;
        }

        private static void GridViewDisposed(object sender, EventArgs e){
            var gridView = (GridView) sender;
            GridViewMenuCommandMap.Remove(gridView);
        }

        private static void GridViewShowGridMenu(object sender, PopupMenuShowingEventArgs e){
            var gridView = (GridView) sender;
            var commands = GridViewMenuCommandMap[gridView];
            if ((commands == null) || (commands.Count == 0)){
                return;
            }
            foreach (GridViewMenuCommand command in commands){
                if (command.MenuType == e.MenuType){
                    command.GridView = gridView;
                    var menuItem = new GridViewMenu(gridView) { Caption = command.Caption, Image = command.Glyph, Tag = command};
                    
                    menuItem.Click += MenuItemClick;
                    e.Menu.Items.Add(menuItem);
                }
            }
        }

        private static void MenuItemClick(object sender, EventArgs e){
            var menuItem = (GridViewMenu) sender;
            var command = (GridViewMenuCommand) menuItem.Tag;
            command.Execute(menuItem.View);
        }

        #endregion 静态方法

        public GridViewMenuCommand(string caption, string description, EventHandler handler)
            : base(caption, description, handler){}

        public GridViewMenuCommand(string caption, string description, Image glyph, EventHandler handler)
            : base(caption, description, glyph, handler){}

        /// <summary>
        /// GridView
        /// </summary>
        public GridView GridView{
            get;
            set;
        }

        /// <summary>
        /// 菜单类型
        /// </summary>
        public GridMenuType MenuType{
            get;
            set;
        }

        public override void Execute(){
            Execute(GridView);
        }
        /// <summary>
        /// 执行命令
        /// </summary>
        /// <param name="gridView"></param>
        public virtual void Execute(GridView gridView){}
    }
}